#include "calibration.h"

Calibration::Calibration(QWidget *parent) : QWizard(parent)
{
    introPage = new IntroCalPage();
    calPage = new CalibrationPage();

    addPage(introPage);
    addPage(calPage);
}


void Calibration::accept() {
    config->calculateCalibration();



    QDialog::accept();
}

void Calibration::setConfig(Config *conf) {
    config = conf;
    calPage->setConfig(config);
}
/** ***************************************************************************
 * Setter for the value of the current connector!
 * Value is set every time, but variable bool calibrationInProgress controls if
 * there is some action with this value
 * ****************************************************************************/
void Calibration::setConnectorValue(int coNumber, float value) {
    calPage->setConnectorValue(coNumber,value);
}


IntroCalPage::IntroCalPage(QWidget *parent)
    : QWizardPage(parent)
{
    setTitle(tr("Introduction"));
    setSubTitle(tr("Welcome to Bimos Pro calibration system"));
    ////setpixmap(QWizard::WatermarkPixmap, QPixmap(":/images/watermark1.png"));

    label = new QLabel(tr("Calibration Text blabla."));
    label->setWordWrap(true);

    QVBoxLayout *layout = new QVBoxLayout;
    layout->addWidget(label);
    setLayout(layout);
}

CalibrationPage::CalibrationPage(QWidget *parent)
    : QWizardPage(parent)
{
    setTitle(tr("Calibration"));
    setSubTitle(tr("Here, you are able to calibrate."));

    // Two layouts to show radiobuttons and progressbar
    QVBoxLayout *vertLayout = new QVBoxLayout;
    QGridLayout *layout = new QGridLayout;
    QGridLayout *layout2 = new QGridLayout;

    /** initialize GUI and variables */

    lowerValueEdit = new QLineEdit();
    upperValueEdit = new QLineEdit();
    lowerValueEdit->setPlaceholderText("Current pressure in mbar");
    upperValueEdit->setPlaceholderText("Current pressure in mbar");
    averageLowerValueLabel = new QLabel("Avg. value: ");
    averageUpperValueLabel = new QLabel("Avg. value: ");
    calibrateBtn = new QPushButton("Calibrate");    
    freezeLowerValueBox = new QCheckBox("Freeze value");
    freezeUpperValueBox = new QCheckBox("Freeze value");
    calibrationRangeValid = false;
    lowerCalibrationInProgress = false;
    upperCalibrationInProgress = false;
    lowerCalibrationDone = false;
    upperCalibrationDone = false;
    calibrationCounter = 0;
    averageLowerValue = 0;
    averageUpperValue = 0;



    /** initialize calibration array */
    for (int i = 0; i < NUMBEROFBOTTLES; i++) {
        for (int j = 0; j < CALIBRATIONSAMPLES; j++) {
            voltValueForConnector[i][j] = -1;
        }
    }

    /** connect buttons and checkboxes */
    connect(freezeLowerValueBox,SIGNAL(toggled(bool)),this,SLOT(freezeLowerValue(bool)));
    connect(freezeUpperValueBox,SIGNAL(toggled(bool)),this,SLOT(freezeUpperValue(bool)));
    connect(calibrateBtn,SIGNAL(clicked()),this,SLOT(calibrateConnector()));

    /** disable button and checkboxes as long as values are not valid */
    calibrateBtn->setEnabled(false);
    lowerValueEdit->setEnabled(false);
    freezeLowerValueBox->setEnabled(false);


    // initialize the radiobuttons
    for (int i = 0; i < NUMBEROFBOTTLES; i++) {
        actBottlesBtn[i] = new QRadioButton(QString::number(i));
        layout->addWidget(actBottlesBtn[i],0,i);
    }

    for (int i = 0; i < NUMBEROFBOTTLES; i++)
        connect(actBottlesBtn[i], SIGNAL(clicked(bool)),this,SLOT(changeActiveBottle(bool)));

    /** init progress bar */
    pBar = new QProgressBar();
    pBar->setRange(0,500);
    pBar->repaint();

    /** set layouting */
    vertLayout->addWidget(pBar,    1, 0);
    vertLayout->addLayout(layout);
    layout2->addWidget(lowerValueEdit,0,0);
    layout2->addWidget(freezeLowerValueBox,0,1);
    layout2->addWidget(upperValueEdit,0,2);
    layout2->addWidget(freezeUpperValueBox,0,3);
    layout2->addWidget(averageLowerValueLabel,1,0);
    layout2->addWidget(averageUpperValueLabel,1,2);
    layout2->addWidget(calibrateBtn,1,4);
    vertLayout->addLayout(layout2);

    setLayout(vertLayout);
}
/** called after constructor, before showing page */
void CalibrationPage::initializePage() {
    QString finishText = wizard()->buttonText(QWizard::FinishButton);
    // select the first active bottle
    for (int i = 0; i < NUMBEROFBOTTLES; i++) {
        if (config->getActiveBottles()[i]) {
            actBottlesBtn[i]->setChecked(true);
            calibrateBtnNumber = i;
            break;
        }
    }
    // disable all not activated bottles
    for (int i = 0; i < NUMBEROFBOTTLES; i++) {
        if (!config->getActiveBottles()[i]) {
            actBottlesBtn[i]->setEnabled(false);
        }

    }

}

void CalibrationPage::checkIfCalibrationIsValid() {
    if (!calibrationRangeValid ) {
        freezeLowerValueBox->setEnabled(false);
        freezeUpperValueBox->setEnabled(false);
        lowerValueEdit->setEnabled(false);
        upperValueEdit->setEnabled(false);
    } else if(calibrationRangeValid && !lowerCalibrationInProgress && !upperCalibrationInProgress) {
        if (!lowerCalibrationDone) {
            freezeLowerValueBox->setEnabled(true);
            lowerValueEdit->setEnabled(true);
        }
        if (lowerCalibrationDone && !upperCalibrationDone) {
            freezeUpperValueBox->setEnabled(true);
            upperValueEdit->setEnabled(true);
        }

    }
}
/** checks if calibration is in progress */
void CalibrationPage::checkIfCalibrationIsInProgress(float value) {
    // Check if lower calibration is in progress
    if (lowerCalibrationInProgress && calibrationCounter < CALIBRATIONSAMPLES ) {
        voltValueForConnector[calibrateBtnNumber][calibrationCounter] = value;
        lowerValueEdit->setEnabled(false);
        freezeLowerValueBox->setEnabled(false);
        upperValueEdit->setEnabled(false);
        freezeUpperValueBox->setEnabled(false);
        calibrationCounter++;

    // Check if lower calibration is done
    } else if (lowerCalibrationInProgress && calibrationCounter == CALIBRATIONSAMPLES) {
        lowerCalibrationDone = true;
        calibrationCounter = 0;
        lowerCalibrationInProgress = false;

        averageLowerValue = 0;

        for (int i = 0; i < CALIBRATIONSAMPLES; i++) {
            averageLowerValue += voltValueForConnector[calibrateBtnNumber][i];
        }
        averageLowerValue /= CALIBRATIONSAMPLES;
        averageLowerValueLabel->setText("Average:" + QString::number(averageLowerValue) );

    // Check if upper calibration is in progress
    } else if (upperCalibrationInProgress && calibrationCounter < CALIBRATIONSAMPLES ) {
        voltValueForConnector[calibrateBtnNumber][calibrationCounter] = value;
        lowerValueEdit->setEnabled(false);
        freezeLowerValueBox->setEnabled(false);
        upperValueEdit->setEnabled(false);
        freezeUpperValueBox->setEnabled(false);
        calibrationCounter++;

    // Check if upper calibration is done
    } else if (upperCalibrationInProgress && calibrationCounter == CALIBRATIONSAMPLES) {
        upperCalibrationDone = true;
        calibrationCounter = 0;
        upperCalibrationInProgress = false;
        averageUpperValue = 0;

        for (int i = 0; i < CALIBRATIONSAMPLES; i++) {
            averageUpperValue += voltValueForConnector[calibrateBtnNumber][i];
        }
        averageUpperValue /= CALIBRATIONSAMPLES;
        averageUpperValueLabel->setText("Average:" + QString::number(averageUpperValue) );
        calibrateBtn->setEnabled(true);


    } else {
        calibrationCounter = 0;
        upperCalibrationInProgress = false;
        lowerCalibrationInProgress = false;
    }
}

void CalibrationPage::setProgressBarColor(float value) {
    if (value < 0.5 || value > 2) {
        calibrationRangeValid = false;
        pBar->setStyleSheet(pBar->property("defaultStyleSheet").toString() + " QProgressBar::chunk { background: red; }");
     } else {
        pBar->setStyleSheet(pBar->property("defaultStyleSheet").toString() + " QProgressBar::chunk { background: green; }");
        calibrationRangeValid = true;
    }
    pBar->setFormat("Volt value: " + QString::number(value) + " V, estimated pressure: " + QString::number(0.47762*(value)+1.2957) + "bar");
    pBar->repaint();

}

void CalibrationPage::setConnectorValue(int conNumber, float value) {

    if (conNumber == calibrateBtnNumber) {
        pBar->setValue((int) ((float) value*100));
        setProgressBarColor(value);
        checkIfCalibrationIsInProgress(value);
        checkIfCalibrationIsValid();
    }
}
/** Triggered when radiobuttons are changed */
void CalibrationPage::changeActiveBottle(bool) {
    QRadioButton *button = (QRadioButton *)sender();
    calibrateBtnNumber = button->text().toInt();
    resetCalibration();
}
/** Setter config */
void CalibrationPage::setConfig(Config *conf) {
    config = conf;
}
/** Triggered when checkbutton for lower value freeze is pushed */
void CalibrationPage::freezeLowerValue(bool checked) {
    if (checked) {
        lowerValueEdit->setEnabled(false);
        lowerPressure = lowerValueEdit->text().toFloat();
        lowerCalibrationInProgress = true;


    } else if (lowerCalibrationDone) {
        lowerValueEdit->setEnabled(false);
        freezeLowerValueBox->setEnabled(false);
    } else if(calibrationRangeValid) {
        lowerValueEdit->setEnabled(true);
    }
}
/** Triggered when checkbutton for upper value freeze is pushed */
void CalibrationPage::freezeUpperValue(bool checked) {
    if (checked) {
        upperValueEdit->setEnabled(false);
        upperPressure = upperValueEdit->text().toFloat();
        upperCalibrationInProgress = true;
    } else if (lowerCalibrationDone) {
        upperValueEdit->setEnabled(false);
        freezeUpperValueBox->setEnabled(false);
    } else if(calibrationRangeValid) {
        upperValueEdit->setEnabled(true);
    }

    //calibrateBtn->setEnabled(true);
}
/** Triggered when calibrate btn is hit, sets automatically to next active connector */
void CalibrationPage::calibrateConnector() {
    config->setLowerCalibrationValue(calibrateBtnNumber,averageLowerValue,lowerPressure);
    config->setUpperCalibrationValue(calibrateBtnNumber,averageUpperValue,upperPressure);

    actBottlesBtn[calibrateBtnNumber]->setEnabled(false);
    if (calibrateBtnNumber != NUMBEROFBOTTLES - 1)
        actBottlesBtn[calibrateBtnNumber + 1]->setChecked(true);

    resetCalibration();
    for (int i = calibrateBtnNumber + 1; i < NUMBEROFBOTTLES; i++) {
        if (config->getActiveBottles()[i]) {
            actBottlesBtn[i]->setChecked(true);
            calibrateBtnNumber = i;
            break;
        }
    }



}
/** resets all significant values for the calibration in order to calibrate another one */
void CalibrationPage::resetCalibration() {
    lowerCalibrationDone = false;
    upperCalibrationDone = false;
    lowerCalibrationInProgress = false;
    upperCalibrationInProgress = false;
    upperValueEdit->setEnabled(true);
    upperValueEdit->setText("");
    upperValueEdit->setPlaceholderText("Current pressure in mbar");
    lowerValueEdit->setEnabled(true);
    lowerValueEdit->setText("");
    lowerValueEdit->setPlaceholderText("Current pressure in mbar");
    averageLowerValueLabel->setText("Average:");
    averageUpperValueLabel->setText("Average:");
    freezeLowerValueBox->setChecked(false);
    freezeUpperValueBox->setChecked(false);

}
